產生PDF寫好了,那在網頁上顯示天氣預報表格吧,寫一個API,只去抓天氣API,CrawlerWeatherAPI()就好,不產生PDF。
原本是想說要在js整理資料,處理資料格式後顯示在表格上(table),發現有點麻煩跟複雜,所以決定還是在後端處理好,前端就只要跑forloop就好。
跟寫pdf的程式很像,把資料整理成兩層的list
ex
[{
locationName: "文山區"
tableDataList: [
["00:00", "22℃", "23℃", "20%", "多雲", "舒適"],
["03:00", "21℃", "23℃", "20%", "陰", "舒適"]
...
]
},
locationName: "松山區"
tableDataList: [
["00:00", "22℃", "23℃", "20%", "多雲", "舒適"],
["03:00", "21℃", "23℃", "20%", "陰", "舒適"]
...
]
},
]
main/views.py 局部程式碼,寫一個 getPdfWeather 處理request
# 轉成兩層List
def convertToList(dataDict):
todayDate = datetime.datetime.today().date()
tomorrow = todayDate + datetime.timedelta(days=1)
tomorrowText = tomorrow.strftime('%Y-%m-%d')
showDateText = tomorrowText
bodyList = [
["00:00"], ["03:00"], ["06:00"], ["09:00"],
["12:00"], ["15:00"], ["18:00"], ["21:00"]
]
def bodyGetIndex(dataTime):
hour = int(dataTime.split(" ")[1].split(":")[0])
bodyIndex = int(hour / 3)
return bodyIndex
for temperatureDict in dataDict["temperatureDictList"]:
dataTime = temperatureDict["dataTime"]
if showDateText in dataTime:
bodyIndex = bodyGetIndex(dataTime)
bodyList[bodyIndex].append(f"{temperatureDict['value']}℃")
# aTemperatureDict 省略
# pop6HDictList 省略
# wxDictList 省略
# ciDictList 省略
return bodyList
def getPdfWeather(request):
locationNameList = request.GET.getlist("locationNameList", [])
crawlerWeatherAPI = CrawlerWeatherAPI()
dataDictList = crawlerWeatherAPI.getCrawlerData(locationNameList)
resultList = []
for dataDict in dataDictList:
resultList.append({
"locationName": dataDict["locationName"],
"tableDataList": convertToList(dataDict)
})
return JsonResponse(resultList, safe=False)
寫一個新的按鈕,習慣會把render html 拉出來寫,看起來比較乾淨,但還是不好閱讀..,大概來說就是用 Bootstrap Card 的樣式,那class="card-header" 就是放地區名稱,那class="card-body"就是放 未來鄉鎮天氣表格table,因為有先在python 整理後,所以就直接用join()把欄位(td)字串組起來。
main/main.html
...
<button id="getPdfWeatherBtn" class="btn btn-primary mr-xs" type="button">
抓取未來鄉鎮天氣預報
</button>
...
<script>
const renderTable = (dataObj) => {
const trArray = dataObj.tableDataList.map((tableDataList) => {
return "<tr><td>" +tableDataList.join("</td><td>")+"</td></tr>"
})
const tableBody = trArray.join("")
return `<table class="table table-bordered table-hover">
<tr>
<th></th><th>溫度</th><th>體感溫度</th><th>降雨機率</th><th>天氣現象</th><th>舒適度</th>
</tr>
${tableBody}
</table>
`
}
const renderWeatherCard = (dataObj) => {
return `
<div class="card">
<div class="card-header">
${dataObj.locationName}
</div>
<div class="card-body">
${renderTable(dataObj)}
</div>
</div>
`
}
const reqGetPdfWeather = (selectedDistrictChxArr) => {
$("#weatherDiv").html("")
const queryString = selectedDistrictChxArr.join('&')
$.ajax({
url: `/api/getPdfWeather/?${queryString}`,
processData: false,
contentType: false,
success: (res) => {
res.map((dataObj) => {
$("#weatherDiv").append(renderWeatherCard(dataObj))
})
}
})
}
$(document).on("click", "#getPdfWeatherBtn", (e) => {
e.preventDefault();
let selectedDistrictChxArr = []
$('.districtChx[name=checkboxDistrict]:checked').each(function (i) {
selectedDistrictChxArr.push(`locationNameList=${this.value}`)
})
reqGetPdfWeather(selectedDistrictChxArr)
})
</script>
結果圖:
結語
寫得有點醜,需要再重構,把重複的程式拉出來做,有時間再來改吧
參考資料: